package com.xunan.demo.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayTradeCreateResponse;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.alipay.api.response.AlipayTradePayResponse;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import lombok.extern.slf4j.Slf4j;
import com.xunan.demo.pojo.CommonResult;
import com.xunan.demo.service.AlipayPaymentService;
import com.xunan.demo.service.AlipayUserService;
import com.xunan.demo.utils.HttpUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * 小程序的参考文档：https://opendocs.alipay.com/mini/introduce/pay
 * 其他的参考文档：https://opendocs.alipay.com/open/00a0ut   开放能力，顺着看
 *
 * API列表中会告诉你整么调用支付功能
 */
@Slf4j
@RestController
public class AlipayPaymentController {

    /**
     * 支付宝小程序支付宝公钥证书路径（绝对位置）
     */
    @Value("${alipay-payment.alipay-mini-app.alipay-public-cert-path}")
    String ALIPAY_MINI_APP_ALIPAY_PUBLIC_CERT_PATH;

    /**
     * Web应用支付宝公钥证书路径（绝对位置）
     */
    @Value("${alipay-payment.web.alipay-public-cert-path}")
    String WEB_ALIPAY_PUBLIC_CERT_PATH;

    @Resource
    AlipayPaymentService alipayPaymentService;

    @Resource
    AlipayUserService alipayUserService;

    /**
     * 支付宝支付消息回调（异步通知）
     * 参考文档：https://opendocs.alipay.com/open/270/105902#%E6%94%AF%E4%BB%98%E6%B8%A0%E9%81%93%E8%AF%B4%E6%98%8E
     *
     * @param params 通过 POST 请求的形式将支付结果作为参数通知到商户系统
     * @return success
     */
    @PostMapping("/alipay-payment/alipayMiniAppPaymentNotify")
    @ResponseBody
    public String alipayMiniAppPaymentNotify(HttpServletRequest params) {
        log.info("请求结果：");
        log.info(String.valueOf(params));

        boolean isVerify = alipayPaymentNotifyVerify(params, ALIPAY_MINI_APP_ALIPAY_PUBLIC_CERT_PATH);
        log.info("支付宝验签结果：" + isVerify);

        //只有返回success，支付宝才会停止本单的回调通知
        return "success";
    }

    /**
     * 支付宝支付消息回调（异步通知）
     * 参考文档：https://opendocs.alipay.com/open/270/105902#%E6%94%AF%E4%BB%98%E6%B8%A0%E9%81%93%E8%AF%B4%E6%98%8E
     *
     * @param params 通过 POST 请求的形式将支付结果作为参数通知到商户系统
     * @return success
     */
    @PostMapping("/alipay-payment/webPaymentNotify")
    @ResponseBody
    public String webPaymentNotify(HttpServletRequest params) {
        log.info("请求结果：");
        log.info(String.valueOf(params));

        boolean isVerify = alipayPaymentNotifyVerify(params, WEB_ALIPAY_PUBLIC_CERT_PATH);
        log.info("支付宝验签结果：" + isVerify);

        //只有返回success，支付宝才会停止本单的回调通知
        return "success";
    }

    /**
     * 获取支付宝小程序支付数据
     *
     * @param price    商品价格
     * @param subject  标题
     * @param userCode 用户授权码（和UserId二选一）
     * @param buyerId  购买用户的UserId（和用户授权码二选一）
     * @return 支付宝小程序支付数据
     */
    @PostMapping("/alipay-payment/getAlipayMiniAppPayData")
    public CommonResult<AlipayTradeCreateResponse> getAlipayMiniAppPayData(
            @RequestParam Double price,
            @RequestParam String subject,
            String userCode,
            String buyerId
    ) {
        //先获取User
        if (buyerId == null) {
            buyerId = alipayUserService.getMiniAppUserInfo(userCode, null).getData().getUserId();
        }

        //如果UserId为空则直接终止
        if (buyerId == null) {
            return new CommonResult<>(false, "无法获取用户信息", null);
        }

        return alipayPaymentService.getAlipayMiniAppPayData(price, subject, buyerId);
    }

    /**
     * 获取电脑网站支付数据
     *
     * @param price   商品价格
     * @param subject 标题
     * @return 支付宝小程序支付数据
     */
    @PostMapping("/alipay-payment/getPagePayData")
    public CommonResult<AlipayTradePagePayResponse> getPagePayData(
            @RequestParam Double price,
            @RequestParam String subject
    ) {
        return alipayPaymentService.getPagePayData(price, subject);
    }

    /**
     * 获取手机网站支付数据
     *
     * @param price   商品价格
     * @param subject 标题
     * @param quitUrl 用户付款中途退出返回商户网站的地址
     * @return 支付宝小程序支付数据
     */
    @PostMapping("/alipay-payment/getWapPayData")
    public CommonResult<AlipayTradeWapPayResponse> getWapPayData(
            @RequestParam Double price,
            @RequestParam String subject,
            @RequestParam String quitUrl
    ) {
        return alipayPaymentService.getWapPayData(price, subject, quitUrl);
    }

    /**
     * 当面付
     *
     * @param price    商品价格
     * @param subject  标题
     * @param authCode 支付授权码
     * @return 支付宝小程序支付数据
     */
    @PostMapping("/alipay-payment/codePay")
    public CommonResult<AlipayTradePayResponse> codePay(
            @RequestParam Double price,
            @RequestParam String subject,
            @RequestParam String authCode
    ) {
        return alipayPaymentService.codePay(price, subject, authCode);
    }

    /**
     * 支付宝参数验证
     *
     * @param params         Http参数
     * @param publicCertPath 公钥证书位置
     * @return 验证结果
     */
    private boolean alipayPaymentNotifyVerify(HttpServletRequest params, String publicCertPath) {
        Map<String, String> requestParamsMap = HttpUtils.convertRequestParamsToMap(params);
        try {
            //验签
            return AlipaySignature.rsaCertCheckV1(requestParamsMap, publicCertPath, "UTF-8", "RSA2");
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return false;
        }

    }
}
